// 在 store 中创建一个模块（WebSocket 模块）
import {Notification} from 'element-ui';
import {getToken} from "@/utils/auth";
import websocket from "@/store/modules/websocket";
import {Loading} from 'element-ui';
// 在JavaScript中，事件处理函数中的异常默认情况下不会直接影响整个JavaScript程序的运行。这是因为事件处理函数是在其自己的执行环境中运行的，当其中发生异常时，这个异常会被捕获并处理，而不会传播到全局作用域中导致整个脚本停止执行。这一机制允许程序的其他部分继续正常工作，提高了程序的稳定性和健壮性。
//
// 具体来说，有以下几点原因：
//
// 错误传播范围限制：当事件处理函数内部发生错误时，这个错误通常只影响该函数的执行环境，而不是全局作用域。这意味着，即使事件处理中抛出了异常，JavaScript引擎也不会中断整个脚本的执行，而是仅在该事件处理上下文中处理异常。
//
// try...catch语句块：虽然你提到的情况默认不会使用try...catch，但实际上，良好的编程实践是将可能出错的代码包裹在try块中，并通过catch来捕获并处理异常。在事件处理函数中使用try...catch可以更加主动地控制异常对程序的影响。
//
// 浏览器或宿主环境的错误处理：浏览器或其他JavaScript宿主环境自身也可能有错误处理机制，它们会捕获未被捕获的异常，从而防止整个页面或应用因为单一错误而完全崩溃。例如，浏览器可能会在开发者工具的控制台中记录错误信息，但不会因此停止所有JavaScript代码的执行。
//
// 异步编程模型：在涉及异步操作（如Promise或async/await）的事件处理中，异常处理尤为重要且复杂。未被捕获的Promise rejection不会直接导致JavaScript程序崩溃，但会在Node.js中触发'unhandledRejection'事件，在某些浏览器环境下可能仅在开发者控制台显示错误信息，同样不会直接影响整个脚本的执行。
//
// 总之，JavaScript设计成这样是为了提高程序的容错能力和持续运行的能力，即使部分功能遇到问题，也不至于让整个应用崩溃。然而，开发者仍然需要关注并适当处理这些异常，以提升用户体验和程序的稳定性。
const state = {
    ws: null,
    heartCheckTimer: null,
    user: null,
};

const mutations = {
    SET_WS(state, ws) {
        state.ws = ws;
        console.log("SET_WS", state.ws);
    },
    CLEAR_WS(state) {
        state.ws = null;
    },
    SET_HEART_CHECK_TIMER(state, timer) {
        state.heartCheckTimer = timer;
    },
    CLEAR_HEART_CHECK_TIMER(state) {
        state.heartCheckTimer = null;
    },
    SET_USER(state, user) {
        state.user = user;
    },
    CLEAR_USER(state) {
        state.user = null;
    },
};

const actions = {
        startWebSocket({commit, dispatch, state}) {
            let user = sessionStorage.getItem('user')
            let userObj = JSON.parse(user)
            // if (user && (!state.ws || state.ws.readyState !== WebSocket.OPEN)) {
            if (state.user && userObj && state.user.token != userObj.token) {// 如果更换用户登录了，或者用户重新登录了，则重新连接
                dispatch('clearWebSocket')
            }
            if (user && !state.ws) {
                // console.log("SOCKET_PATH:", process.env);
                // const socketUrl = `${process.env.VUE_APP_SOCKET_PATH}?token=${getToken()}`;
                const socketUrl = `${process.env.VUE_APP_SOCKET_PATH}?token=${userObj.token}`;
                const ws = new WebSocket(socketUrl);
                // 保存 WebSocket 连接信息
                commit('SET_WS', ws);
                commit('SET_USER', userObj)

                ws.onmessage = function (e) {
                    console.log(`${new Date().toLocaleString()} >>>>> 收到消息 ${e.data}`, state.ws);
                    if (e.data == "pong") {
                        return
                        // Notification({
                        //     type: "info",
                        //     title: '新消息',
                        //     message: e.data,
                        //     position: "top-right",
                        //     duration: 3000,
                        //     showClose: true
                        // });
                    }
                    let msg = null
                    try{
                        msg = JSON.parse(e.data);
                    }catch (e){
                        console.log("e.data", e.data);
                        Notification({
                            type: "error",
                            title: '错误',
                            message: e.data,
                            position: "top-right",
                            duration: 3000,
                            showClose: true
                        });
                        return
                    }
                    // console.log('----------------')
                    // console.log(e.data);

                    if (msg.type == "batchstop_info") {
                        Notification({
                            type: "info",
                            title: '新消息',
                            message: msg.message,
                            position: "top-right",
                            duration: 3000,
                            showClose: true
                        });
                        // Loading.service({
                        //     fullscreen: true,
                        //     lock: true,
                        //     text: msg.message,
                        //     spinner: 'el-icon-loading',
                        //     background: 'rgba(0, 0, 0, 0.7)'
                        // });
                        // Loading.service({fullscreen: true,}).text=msg.message;

                        return;
                    }else if( msg.type == "batchstop_err"){

                        // Loading.service({
                        //     fullscreen: true,
                        //     lock: true,
                        //     text: msg.message,
                        //     spinner: 'el-icon-loading',
                        //     background: 'rgba(0, 0, 0, 0.7)'
                        // });
                        // Loading.service({fullscreen: true,}).text=msg.message;

                        Notification({
                            type: "error",
                            title: '错误',
                            message: msg.message,
                            position: "top-right",
                            duration: 3000,
                            showClose: true
                        });
                        return
                    }
                    else if( msg.type == "batchstop_over"){

                        // let loading = Loading.service({
                        //     fullscreen: true,
                        //     lock: true,
                        //     text: msg.message,
                        //     spinner: 'el-icon-loading',
                        //     background: 'rgba(0, 0, 0, 0.7)'
                        // });
                        // loading.text = msg.message;
                        // loading.close();
                        Notification({
                            type: "info",
                            title: '批量停机结束！',
                            message: msg.message,
                            position: "top-right",
                            duration: 0,
                            showClose: true
                        });
                        return
                    }
                }
                ;

                ws.onclose = function () {
                    console.log(`${new Date().toLocaleString()} >>>>> 连接已关闭`);
                    // 尝试重新连接
                    // dispatch('reconnectWebSocket');
                };

                ws.onopen = function () {
                    console.log(`${new Date().toLocaleString()} >>>>> 连接成功`, ws);
                    Notification({
                        type: "success",
                        title: '成功',
                        message: '会话连接成功',
                        position: "top-right",
                        duration: 3000,
                        showClose: true
                    });
                    // 开始心跳检测
                    dispatch('startHeartCheck');
                };
                //连接失败！新建websocket连接失败后触发。
                //网上有文章说这个onerror事件没什么用，可以忽略！！   用心跳检测来判断网络中断情况以及进行重连即可。
                //经测试，连接建立失败，无法与服务器建立连接时触发。
                // 也就是new Websocket()如果没有成功，会触发onerror，如果成功，就触发onopen。所以这里要调用重连函数
                //发送消息出错异常并不会触发onerror！
                ws.onerror = function (e) {
                    console.log(`${new Date().toLocaleString()} >>>>> 数据传输发生异常`, e);
                    Notification({
                        type: "error",
                        title: '错误',
                        message: '会话连接异常，服务已断开,尝试重连。。。',
                        position: "top-right",
                        duration: 3000,
                        showClose: true
                    });
                    dispatch('reconnectWebSocket');
                };
            }
        },

        sendWebSocketMessage({state}, msg) {
            console.log(`${new Date().toLocaleString()} >>>>> 发送消息：${msg}`, state.ws);
            if(msg == 'ping'){
                state.ws.send(msg);
                return
            }
            let msgO = null
            try {
                msgO = JSON.parse(msg)
            } catch (e) {
                console.log("sendWebSocketMessage", e)
            }
            // if (msgO && msgO.type == "batchstop") {
            //     Loading.service({
            //         fullscreen: true,
            //         lock: true,
            //         text: '批量停机命令执行中，请稍等。。。',
            //         spinner: 'el-icon-loading',
            //         background: 'rgba(0, 0, 0, 0.7)'
            //     });
            // }
            state.ws.send(msg);
        }
        ,

        reconnectWebSocket({dispatch}) {
            dispatch('clearWebSocket');
            // 递归调用，一直尝试重连  //这是原作者的注释，但是这里并没有递归
            setTimeout(() => {
                dispatch('startWebSocket');
            }, 6000);
        }
        ,

        clearWebSocket({commit, dispatch, state}) {
            if (state.ws) {
                dispatch('clearHeartCheckTimer');
                state.ws.close();
                commit('CLEAR_WS');
                commit('CLEAR_USER')
            }
        }
        ,

        startHeartCheck({commit, dispatch, state}) {
            console.log(`${new Date().toLocaleString()} >>>>> 开始心跳检测`, state.ws);
            // 清除之前的计时器
            dispatch('clearHeartCheckTimer');

            // 创建新的计时器
            dispatch('sendWebSocketMessage', 'ping');
            const timer = setInterval(() => {
                if (!state.ws || state.ws.readyState !== WebSocket.OPEN) {
                    console.log(`${new Date().toLocaleString()} >>>>> 心跳检测失败,触发重连`, state.ws);
                    dispatch('reconnectWebSocket');
                } else {
                    console.log(`${new Date().toLocaleString()} >>>>> 心跳正常,继续下一次心跳检测`, state.ws);
                    dispatch('sendWebSocketMessage', 'ping');
                }
            }, 1000 * 10);
            commit('SET_HEART_CHECK_TIMER', timer);
        }
        ,

        clearHeartCheckTimer({commit, state}) {
            const timer = state.heartCheckTimer;
            timer && clearInterval(timer);
            commit('CLEAR_HEART_CHECK_TIMER');
        }
        ,
    }
;

export default {
    state,
    mutations,
    actions,
};


